package com.kamistoat.meimeimall.meimeimallorder.listener;

import com.kamistoat.meimeimall.common.To.RabbitMQTo.OrderTo;
import com.kamistoat.meimeimall.common.runTimeFunc.RunTimeLog;
import com.kamistoat.meimeimall.meimeimallorder.config.AlipayTemplate;
import com.kamistoat.meimeimall.meimeimallorder.service.OrderService;
import com.rabbitmq.client.Channel;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;


@Service
public class OrderCloseListener {

    @Autowired
    OrderService orderService;
    @Autowired
    AlipayTemplate alipayTemplate;
    @Autowired
    RedissonClient redissonClient;

    @RabbitListener(queues = "order.release.order.queue")
    public void releaseListener(Message message, OrderTo orderTo, Channel channel) {
        RunTimeLog.printRunTimeLog("检查超时订单==>" + orderTo.getOrderSn());
        // 向RabbitMQ手动进行ack
        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        // 要修改订单状态，获取锁
        RLock orderStatusModifyLock = redissonClient.getLock("order:orderStatusModify:rLock:" + orderTo.getOrderSn());
        orderStatusModifyLock.lock(2, TimeUnit.SECONDS);
        try {
            // 直接将关单也放在try中，防止关单时出现异常
            orderService.closeOrder(orderTo);
            // 成功关单后，同时关闭支付宝的支付通道
            alipayTemplate.close(orderTo.getOrderSn());
            // 假如关单服务异常，或者手动ack时异常，都会进入catch
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            e.printStackTrace();
            try {
                // 无论是关单服务异常，还是手动ack异常，都会手动rck
                // 强制再进行一次关单，这是确保成功关闭的操作
                channel.basicReject(deliveryTag, true);
                alipayTemplate.close(orderTo.getOrderSn());
            } catch (Exception ioException) {
                ioException.printStackTrace();
            }
        } finally {
            orderStatusModifyLock.unlock();
        }
    }

}
